﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Thor.Common;
using Thor.Domain;

namespace Thor.Models
{
    public class SingleDayCalendar
    {
        public SingleDayCalendar(Calendar calendar)
        {
            if (calendar == null)
                throw new ArgumentNullException("calendar");

            this.Calendar = calendar;
            this.Id = calendar.CalendarEmail;
            this.Name = calendar.Alias;
            this.Timestamp = calendar.Now.ToLongDateString();
            this.Timezone = calendar.TimeZone;

            this.Entries = BuildEntriesFromCalendar(calendar);

            ApplyTimeframeToEntries();
        }

        public string Id { get; set; }
        public string Name { get; set; }
        public string Timestamp { get; set; }
        public string Timezone { get; set; }
        public string Message { get; set; }
        public List<CalendarEntry> Entries { get; set; }
        public Calendar Calendar { get; set; }

        private List<CalendarEntry> BuildEntriesFromCalendar(Calendar calendar)
        {
            if (calendar != null)
            {
                List<CalendarEntry> entries = new List<CalendarEntry>();

                DateTime dateTimeUtc = DateTime.UtcNow;

                TimeZoneManager timeZoneManager = new TimeZoneManager();
                DateTime dateTimeLocal = timeZoneManager.ConvertTimeFromUtc(dateTimeUtc, calendar.TimeZone);

                DateTime start = new DateTime(dateTimeLocal.Year, dateTimeLocal.Month, dateTimeLocal.Day, 0, 0, 0);
                DateTime end = new DateTime(dateTimeLocal.Year, dateTimeLocal.Month, dateTimeLocal.Day, 0, 29, 59);

                for (int i = 0; i <= 47; i++)
                {
                    var isBusy = calendar.IsBusy(start, end);
                    var isOffHours = calendar.IsOffHours(start);
                    var isCurrent = calendar.IsCurrentTime(start, end);
                    string displayText = string.Empty;

                    if (isBusy)
                    {
                        var appointment = calendar.GetAppointment(start, end);

                        var previousStart = start.AddMinutes(-30);
                        var previousEnd = end.AddMinutes(-30);

                        var previousAppoint = calendar.GetAppointment(previousStart, previousEnd);

                        if (previousAppoint != null && appointment != null)
                        {
                            if (appointment.Subject.ToLower() == previousAppoint.Subject.ToLower())
                                displayText = string.Empty;
                        }
                        else if (appointment != null)
                        {
                            if (calendar.DisplaySubject)
                                displayText = appointment.Subject.ToLower();
                            else
                                displayText = "booked";
                        }
                        else
                            displayText = "booked";
                    }

                    entries.Add(new CalendarEntry(start, !isBusy, isOffHours, isCurrent, calendar.Id, calendar.Alias, calendar.CalendarEmail, displayText));

                    start = start.AddMinutes(30);
                    end = end.AddMinutes(30);
                }

                return entries;
            }

            return null;
        }

        private void ApplyTimeframeToEntries()
        {
            if (Calendar.UseTimeframe && Calendar.StartTime.HasValue && Calendar.EndTime.HasValue)
            {
                List<CalendarEntry> filteredEntries = new List<CalendarEntry>();
                var timeframe = Time.GetTimeframe(Calendar.StartTime.Value, Calendar.EndTime.Value);

                foreach (CalendarEntry entry in this.Entries)
                {
                    string entryTime = entry.Time.ToShortTimeString().ToLower();

                    if (timeframe.Any(t => t.Text.ToLower() == entryTime))
                        filteredEntries.Add(entry);
                }

                Entries = filteredEntries;
            }
        }
    }
}